from typing import Annotated

from fastapi import Depends
from sqlalchemy import delete, func, insert, select, update

from forward.api.admin.orm.lucky.draw import DrawORM
from forward.api.admin.schemas.lucky.draw import (
    DrawAddInSchema,
    DrawDeleteInSchema,
    DrawDetailInSchema,
    DrawEditInSchema,
    DrawListInSchema,
    DrawStatusInSchema,
)
from forward.dependencies.database import db
from forward.extend.pydantic.result_api import ResultAPI
from forward.model.schemas.lucky.draw import DrawOutSchema
from forward.model.tables.activity import DrawModel
from forward.utils.urls import UrlUtil


class DrawService:
    def __init__(self, draw_orm: Annotated[DrawORM, Depends()]) -> None:

        self.draw_orm = draw_orm

    async def lists(self, list_in: DrawListInSchema):
        where = []

        statement = (
            select(DrawModel)
            .where(*where)
            .order_by(DrawModel.id.desc())
            .limit(list_in.page_size)
            .offset((list_in.page_num - 1) * list_in.page_size)
        )
        records = await db.fetch_all(statement)
        statement_count = select(func.count(DrawModel.id)).where(*where)
        count = await db.fetch_val(statement_count)
        lists = [
            DrawOutSchema.model_validate(record, from_attributes=True)
            for record in records
        ]
        for item in lists:
            if item.img_head:
                item.img_head = await UrlUtil.to_absolute_url(item.img_head)
        return ResultAPI(data={"lists": lists, "count": count})

    async def add(self, add_in: DrawAddInSchema):
        if add_in.img_head:
            add_in.img_head = await UrlUtil.to_relative_url(add_in.img_head)
        statement = insert(DrawModel).values(add_in.model_dump())
        await db.execute(statement)
        return ResultAPI()

    async def edit(self, edit_in: DrawEditInSchema):
        if edit_in.img_head:
            edit_in.img_head = await UrlUtil.to_relative_url(edit_in.img_head)
        statement = (
            update(DrawModel)
            .where(DrawModel.id == edit_in.id)
            .values(edit_in.model_dump())
        )
        await db.execute(statement)
        return ResultAPI()

    async def detail(self, detail_in: DrawDetailInSchema):
        statement = select(DrawModel).where(DrawModel.id == detail_in.id)
        record = await db.fetch_one(statement)
        draw = DrawOutSchema.model_validate(record, from_attributes=True)
        if draw.img_head:
            draw.img_head = await UrlUtil.to_absolute_url(draw.img_head)
        return ResultAPI(data=draw)

    async def delete(self, delete_in: DrawDeleteInSchema):
        stetement = delete(DrawModel).where(DrawModel.id == delete_in.id)
        await db.execute(stetement)
        return ResultAPI()

    async def status(self, status_in: DrawStatusInSchema):
        statement = (
            update(DrawModel)
            .where(DrawModel.id == status_in.id)
            .values(status_in.model_dump())
        )
        await db.execute(statement)
        return ResultAPI()

    async def one_by_id(self, id: int):
        statement = select(DrawModel).where(DrawModel.id == id)
        record = await db.fetch_one(statement)
        draw = DrawOutSchema.model_validate(record, from_attributes=True)
        if draw.img_head:
            draw.img_head = await UrlUtil.to_absolute_url(draw.img_head)
        return draw
